﻿// -----------------------------------------------------------------------
// <copyright file="Pixel.cs" company="FCIS">
// You are welcome to do whatever you want with the code in this file
// </copyright>
// -----------------------------------------------------------------------

namespace ImagePackage.Model
{
    using System.Runtime.InteropServices;

    /// <summary>
    /// Represents the pixel
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct Pixel
    {
        /// <summary>
        /// blue component of pixel
        /// </summary>
        private byte blue;

        /// <summary>
        /// green component of pixel
        /// </summary>
        private byte green;

        /// <summary>
        /// red component of pixel
        /// </summary>
        private byte red;

        /// <summary>
        /// alpha component of pixel
        /// </summary>
        private byte alpha;

        /// <summary>
        /// Initializes a new instance of the <see cref="Pixel"/> struct.
        /// </summary>
        /// <param name="red">The red.</param>
        /// <param name="green">The green.</param>
        /// <param name="blue">The blue.</param>
        /// <param name="alpha">The alpha.</param>
        public Pixel(byte red, byte green, byte blue, byte alpha)
        {
            this.red = red;
            this.green = green;
            this.blue = blue;
            this.alpha = alpha;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Pixel"/> struct.
        /// </summary>
        /// <param name="red">The red.</param>
        /// <param name="green">The green.</param>
        /// <param name="blue">The blue.</param>
        public Pixel(byte red, byte green, byte blue)
            : this(red, green, blue, 255)
        {
        }

        /// <summary>
        /// Gets or sets the red.
        /// </summary>
        /// <value>
        /// The red.
        /// </value>
        public byte Red
        {
            get { return this.red; }
            set { this.red = value; }
        }

        /// <summary>
        /// Gets or sets the green.
        /// </summary>
        /// <value>
        /// The green.
        /// </value>
        public byte Green
        {
            get { return this.green; }
            set { this.green = value; }
        }

        /// <summary>
        /// Gets or sets the blue.
        /// </summary>
        /// <value>
        /// The blue.
        /// </value>
        public byte Blue
        {
            get { return this.blue; }
            set { this.blue = value; }
        }

        /// <summary>
        /// Gets or sets the alpha.
        /// </summary>
        /// <value>
        /// The alpha.
        /// </value>
        public byte Alpha
        {
            get { return this.alpha; }
            set { this.alpha = value; }
        }

        /// <summary>
        /// Implements the plus operation and it cuts off.
        /// </summary>
        /// <param name="pixel">The pixel.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static Pixel operator +(Pixel pixel, sbyte value)
        {
            int red = pixel.red + value <= 255 ? (pixel.red + value < 0 ? 0 : pixel.red + value) : 255;
            int green = pixel.green + value <= 255 ? (pixel.green + value < 0 ? 0 : pixel.green + value) : 255;
            int blue = pixel.blue + value <= 255 ? (pixel.blue + value < 0 ? 0 : pixel.blue + value) : 255;

            Pixel result = new Pixel((byte)red, (byte)green, (byte)blue);

            return result;
        }

        /// <summary>
        /// Implements the operator ~.
        /// </summary>
        /// <param name="pixel">The pixel.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static Pixel operator ~(Pixel pixel)
        {
            byte red = (byte)(255 - pixel.red);
            byte green = (byte)(255 - pixel.green);
            byte blue = (byte)(255 - pixel.blue);

            Pixel result = new Pixel(red, green, blue);

            return result;
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="ImagePackage.Model.Pixel"/> to <see cref="ImagePackage.Model.PixelDouble"/>.
        /// </summary>
        /// <param name="pixel">The pixel.</param>
        /// <returns>
        /// The result of the conversion.
        /// </returns>
        public static implicit operator PixelDouble(Pixel pixel)
        {
            PixelDouble result = new PixelDouble(pixel.red, pixel.green, pixel.blue);

            return result;
        }

        /// <summary>
        /// String representation of the Pixel
        /// </summary>
        /// <returns>a string reprsentation of the Alpha, Red, Green and Blue components</returns>
        public override string ToString()
        {
            return string.Format("Alpha {0} ; Red {1} ; Green {2} ; Blue {3}", this.alpha, this.red, this.green, this.blue);
        }
    }
}
